/**
 * 
 */
package net.mikoo.seals.biz.service.impl;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;

import net.mikoo.seals.biz.common.BaseServices;
import net.mikoo.seals.biz.mapper.CompanyMapper;
import net.mikoo.seals.biz.mapper.OrganizationMapper;
import net.mikoo.seals.biz.mapper.PartyMapper;
import net.mikoo.seals.biz.mapper.PersonMapper;
import net.mikoo.seals.biz.mapper.SealMapper;
import net.mikoo.seals.biz.mapper.StaffMapper;
import net.mikoo.seals.biz.mapper.UserLoginMapper;
import net.mikoo.seals.biz.model.PartyType;
import net.mikoo.seals.biz.service.PartyServices;
import net.mikoo.seals.common.WebContext;
import net.mikoo.seals.common.enums.MobileStatusEnum;
import net.mikoo.seals.common.enums.PartyStatusEnum;
import net.mikoo.seals.common.enums.StaffStatusEnum;
import net.mikoo.seals.common.enums.StaffTypeEnum;
import net.mikoo.seals.common.exception.DataNotFoundException;
import net.mikoo.seals.common.exception.ParametersException;
import net.mikoo.seals.common.model.PageModel;
import net.mikoo.seals.model.CompanyQuery;
import net.mikoo.seals.model.Organization;
import net.mikoo.seals.model.OrganizationParty;
import net.mikoo.seals.model.OrganizationQuery;
import net.mikoo.seals.model.Party;
import net.mikoo.seals.model.PartyQuery;
import net.mikoo.seals.model.Person;
import net.mikoo.seals.model.SealQuery;
import net.mikoo.seals.model.Staff;
import net.mikoo.seals.model.StaffQuery;
import net.mikoo.seals.model.UserLogin;
import net.mikoo.seals.utils.IPUtil;
import net.mikoo.seals.utils.MD5Util;

/**
 * @author huangxm
 *
 */
@Service
public class PartyServicesImpl extends BaseServices implements PartyServices {
	
	private Logger logger = Logger.getLogger(PartyServicesImpl.class);
	
	@Autowired
	private PartyMapper		partyMapper;
	
	@Autowired
	private UserLoginMapper	userLoginMapper;
	
	@Autowired
	private PersonMapper	personMapper;
	
	@Autowired
	private StaffMapper staffMapper;
	
	@Autowired
	private OrganizationMapper organizationMapper;
	
	
	@Override
	public Party loadByPrimaryKey(Long partyId) {

		if (partyId == null) {
			throw new ParametersException("partyId is null");
		}

		Party party = partyMapper.selectByPrimaryKey(partyId);
		return party;

	}
	
	@Override
	public void modifyByPrimaryKey(Party party) {
		
		
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus status) {
				if (party == null) {
					throw new ParametersException("party is null!");
				}
				
				if(party.getPartyId() == null) {
					throw new ParametersException("PartyId is null!");
				}
				
				partyMapper.updateByPrimaryKey(party);
				// 修改登录用户信息
//				userLoginMapper.updateByPrimaryKey(party.getUserLogin());
				// 修改person信息
				personMapper.updateByPrimaryKey(party.getPerson());
				
				
				staffMapper.update(party.getStaff());
				
			}
		});

	}
	
	@Override
	public PageModel<Party> getPageByQuery(PartyQuery query) {

		List<Party> datas = partyMapper.selectPageByQuery(query);
		Integer total = partyMapper.countPageByQuery(query);
		PageModel<Party> pm = new PageModel<Party>(total, datas);
		return pm;
	}
	
	/**
	 * 判断字段是否唯一
	 * @param verifykey
	 * @param excludeKey
	 * @param type
	 * @return
	 */
	private boolean isExist(String verifykey, String excludeKey, String type) {
		boolean b = false;
		switch (type) {
			case "username":
				
				UserLogin userLogin = userLoginMapper.selectByUserLoginId(verifykey);
				if (userLogin == null) {
					b = false;
				} else {
					
					b = true;
					if (StringUtils.isNotBlank(excludeKey)) {
						if (verifykey.equals(userLogin.getUserLoginId())) {
							b = false;
						}
					}
				}
				break;
			
			case "mobile":
				Person mPerson = personMapper.selectByMobile(verifykey);
				if (mPerson == null) {
					b = false;
				} else {
					
					b = true;
					
					if (StringUtils.isNotBlank(excludeKey)) {
						if (verifykey.equals(mPerson.getMobile())) {
							b = false;
						}
					}
				}
				break;
			
			case "email":
				
				Person ePerson = personMapper.selectByEmail(verifykey);
				if (ePerson == null) {
					b = false;
				} else {
					b = true;
					if (StringUtils.isNotBlank(excludeKey)) {
						if (verifykey.equals(ePerson.getEmail())) {
							b = false;
						}
					}
				}
				
				break;
			default:
				
				break;
		}
		
		return b;
	}
	
	@Override
	public Boolean checkExist(String verifykey, String excludeKey, String type) {

		if (StringUtils.isBlank(verifykey)) {
			throw new ParametersException("校验值为空");
		}

		if (StringUtils.isBlank(type)) {
			throw new ParametersException("校验值为空");
		}

		boolean b = isExist(verifykey, excludeKey, type);

		return b;
	}
	
	@Override
	public void create(final Party party) {
		
		
		
		
		
		
		Party extisPart = partyMapper.selectByUserLoginId(party.getUserLoginId(), null);
		
		
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus status) {
				
				
				try {
					
					if (extisPart != null) {
						party.setPartyId(extisPart.getPartyId());
						createStaff(party, extisPart);
					} else {
						createParty(party);
					}
					
					
					Person person = party.getPerson();
					String dept = person.getDept();
					Staff staff = party.getStaff();
					
					if(StringUtils.isNotBlank(dept)) {
						OrganizationQuery query = new OrganizationQuery();
						query.setName(dept);
						query.setCompanyId(party.getCompanyId());
						Organization  orgs = organizationMapper.selectInfoByQuery(query);
						
						if(orgs == null) {
							String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase();
							orgs =  new Organization();
							orgs.setCompanyId(party.getCompanyId());
							orgs.setName(dept);
							orgs.setParentId(0L);
							orgs.setOrganizationUid(uuid);
							orgs.setOrgsChain(uuid);
							organizationMapper.insert(orgs);
							
							
							
							OrganizationParty op = new OrganizationParty();
							op.setCompanyId(party.getCompanyId());
							op.setPartyId(party.getPartyId());
							op.setOrganizationId(orgs.getOrganizationId());
							
							organizationMapper.insertParty(op);
						}else {
							OrganizationParty op = new OrganizationParty();
							op.setCompanyId(party.getCompanyId());
							op.setPartyId(party.getPartyId());
							op.setOrganizationId(orgs.getOrganizationId());
							organizationMapper.insertParty(op);
						}
					}
					
					if(staff != null && staff.getOrgId() !=null) {
						OrganizationParty op = new OrganizationParty();
						op.setPartyId(party.getPartyId());
						op.setOrganizationId(staff.getOrgId());
						organizationMapper.insertParty(op);
					}
					
					
				}catch (ParametersException e) {
					logger.error(e);
					status.setRollbackOnly();
					throw e;
				}catch (Exception e) {
					logger.error(e);
					status.setRollbackOnly();
					throw e;
				}

			}
		});
		
		
	}
	
	private void createStaff(Party party,Party extisPart) {
		
		
		
		StaffQuery query = new StaffQuery();
		query.setCompanyId(party.getCompanyId());
		query.setPartyId(extisPart.getPartyId());
		Staff staff = staffMapper.selectInfoByQuery(query);
		if(staff != null) {
			throw new ParametersException("账户已存在");
		}
		
		staff = new Staff();
		staff.setIsSystem("N");
		staff.setPartyId(extisPart.getPartyId());
		staff.setStaffType(StaffTypeEnum.STAFF.code());
		staff.setCompanyId(party.getCompanyId());
		staff.setName(extisPart.getPerson().getName());
		staff.setMobile(extisPart.getPerson().getMobile());
		staff.setIsSystem(party.getIsSystem());
		staff.setCreateTime(new Date());
		staff.setStaffStatus(StaffStatusEnum.NORMAL.code());
		staff.setPosition(party.getPerson().getPosition());
		staffMapper.insert(staff);
		
	}
	
	private void createParty(Party party) {
		
		// 验证用户名
		UserLogin userLogin = party.getUserLogin();
		Person person = party.getPerson();
		String userLoginId = userLogin.getUserLoginId();
		if (StringUtils.isBlank(userLoginId)) {
			throw new ParametersException("登陆账户不能为空");
		}

		boolean b = isExist(userLoginId, null, "username");
		if (b) {
			throw new ParametersException("登陆账户已存在");

		}
		// 验证密码字段
		String password = userLogin.getCurrentPassword();
		if (StringUtils.isBlank(password)) {
			throw new ParametersException("password is blank");
		}

		String email = person.getEmail();
		if (StringUtils.isNotBlank(email) && isExist(email, null, "email")) {
			throw new ParametersException("邮箱账户已存在");
		}

		String mobile = person.getMobile();
		if (StringUtils.isNotBlank(mobile) && isExist(mobile, null, "mobile")) {
			throw new ParametersException("手机号码已存在");
		}

		// 创建party
		party.setUserLoginId(userLogin.getUserLoginId());
		party.setCreatedTime(new Date());
		party.setPartyStatus(PartyStatusEnum.NORMAL.code());
		partyMapper.insertBackPrimaryKey(party);

		// 创建登录帐户

		userLogin.setCurrentPassword(MD5Util.Md5(userLogin.getCurrentPassword()));
		userLogin.setPartyId(party.getPartyId());
		userLogin.setRegisterTime(new Date());
		userLogin.setRegisterIp(IPUtil.getRemoteAddr(WebContext.getRequest()));
		userLoginMapper.insert(userLogin);

		// 创建人员信息
		person.setUserLoginId(userLogin.getUserLoginId());
		person.setPartyId(party.getPartyId());
		person.setMobile(userLogin.getUserLoginId());
		person.setMobileStatus(MobileStatusEnum.NOT_CERTIFIED.code());
		personMapper.insert(person);

		//创建与公司的关系
		Staff staff = new Staff();
		staff.setIsSystem("N");
		staff.setPartyId(party.getPartyId());
		staff.setStaffType(StaffTypeEnum.STAFF.code());
		staff.setCompanyId(party.getCompanyId());
		staff.setName(person.getName());
		staff.setMobile(person.getMobile());
		staff.setIsSystem(party.getIsSystem());
		staff.setCreateTime(new Date());
		staff.setPosition(person.getPosition());
		staffMapper.insert(staff);
		
	}
	
	
	
	
	@Override
	public void deleteByPrimaryKey(Long partyId) {

		if (partyId == null) {
			throw new ParametersException("partyId is null!");
		}
		partyMapper.deleteByPrimaryKey(partyId);

//		// 删除当事人角色信息
//		partyRoleMapper.deleteByPartyId(partyId);

	}

	
	
	@Override
	public void changeStatus(Long partyId, String status) {

		if (partyId == null) {
			throw new ParametersException("partyId is null!");
		}
		Party party = new Party();
		party.setPartyId(partyId);
		if (status.equals("freeze")) {
			party.setPartyStatus(PartyStatusEnum.FREEZE.toString());
		} else {
			party.setPartyStatus(PartyStatusEnum.NORMAL.toString());
		}
		partyMapper.updateByPrimaryKey(party);

	}

	@Override
	public List<Party> getListByQuery(PartyQuery query) {
		if(query == null) {
			throw new ParametersException("query");
		}
		
		return partyMapper.selectListByQuery(query);
	}

	@Override
	public Party getInfoByQuery(PartyQuery query) {
		if(query == null) {
			throw new ParametersException("query");
		}
		
		return partyMapper.selectInfoByQuery(query);
	}

	@Autowired
	private SealMapper sealMapper;
	
	@Autowired
	private CompanyMapper companyMapper;
	
	@Override
	public PartyType getPartyType(Long partyId, Long companyId) {
		
		if(partyId == null || companyId == null) {
			throw new ParametersException("参数错误");
		}
		
		Party party = partyMapper.selectByPrimaryKey(partyId);
		if(party == null) {
			throw new DataNotFoundException("party is not found");
		}
		
		StaffQuery staffQuery = new StaffQuery();
		staffQuery.setPartyId(partyId);
		staffQuery.setCompanyId(companyId);
		staffQuery.setStaffType("LEGAL_PERSON");
		Staff staff = staffMapper.selectInfoByQuery(staffQuery);
		if(staff != null) {
			return PartyType.LEGAL_PERSON;
		}
		
		CompanyQuery companyQuery = new CompanyQuery();
		companyQuery.setUserLoginId(party.getUserLoginId());
		companyQuery.setCompanyId(companyId);
		Integer companyCount = companyMapper.countByQueryToPage(companyQuery);
		if(companyCount > 0) {
			return PartyType.SYSTEM_ADMIN;
		}
		
		SealQuery sealQuery = new SealQuery();
		sealQuery.setPartyId(partyId);
		sealQuery.setCompanyId(companyId);
		Integer sealCount = sealMapper.countPageByQuery(sealQuery);
		
		if(sealCount > 0) {
			return PartyType.DEVICES_ADMIN;
		}
		
		sealQuery.setPartyId(null);
		sealQuery.setInterimPartyId(partyId);
		sealCount = sealMapper.countPageByQuery(sealQuery);
		
		if(sealCount > 0) {
			return PartyType.INTERIM_ADMIN;
		}
		
		return PartyType.NORMAL;
	}
	
}
